﻿using System.Linq;
using HighDiveAdmin.Handlers;
using HighDiveEngine.Aggregates;
using HighDiveEngine.Model;
using HighDiveEngine.Resources;
using NUnit.Framework;
using UnitTestHighDive;

namespace ModelTestHighDive
{
    public class ModelTestContest
    {
        [Test]
        public void ContestSimulationWithoutDb()
        {
            var contest = new Contest
            {
                Name = "Galaxmästerskapen",
                Date = "2015-02-04",
                Club = "Solens Simklubb",
                JudgeList = new JudgeList(5),
                City = "Simhallsavdelningen",
                Country = "Dödsstjärnan",
                DiveHistory = new DiveList(),
                DiveQueue = new DiveList()
            };

            //Hoppare
            var diver1 = new Diver { IdNumber = "011133", FirstName = "Egbert", LastName = "hej", Gender = Gender.Male, Address = "Gatansgata 20", StartNumber = 1 };
            var diver2 = new Diver { IdNumber = "020645", FirstName = "Egbert", LastName = "hej", Gender = Gender.Male, Address = "Gatansgata 21", StartNumber = 2 };
            var diver3 = new Diver { IdNumber = "191261", FirstName = "Egbert", LastName = "hej", Gender = Gender.Male, Address = "Gatansgata 22", StartNumber = 3 };
            var diver4 = new Diver { IdNumber = "210552", FirstName = "Egbert", LastName = "hej", Gender = Gender.Male, Address = "Gatansgata 23", StartNumber = 4 };
            var diver5 = new Diver { IdNumber = "270451", FirstName = "Egbert", LastName = "hej", Gender = Gender.Male, Address = "Gatansgata 24", StartNumber = 5 };
            var diver6 = new Diver { IdNumber = "010101", FirstName = "Egbert", LastName = "hej", Gender = Gender.Male, Address = "Gatansgata 25", StartNumber = 6 };
            var diver7 = new Diver { IdNumber = "120819", FirstName = "Egbert", LastName = "hej", Gender = Gender.Male, Address = "Gatansgata 26", StartNumber = 7 };

            //Domare
            var judge1 = new Judge { IdNumber = "191260", FirstName = "Egberta", LastName = "hej", Gender = Gender.Female, JudgeNumber = 1, Address = "Gatansgata 15" };
            var judge2 = new Judge { IdNumber = "190954", FirstName = "Egberta", LastName = "hej", Gender = Gender.Female, JudgeNumber = 2, Address = "Gatansgata 16" };
            var judge3 = new Judge { IdNumber = "010203", FirstName = "Egberta", LastName = "hej", Gender = Gender.Female, JudgeNumber = 3, Address = "Gatansgata 17" };
            var judge4 = new Judge { IdNumber = "151012", FirstName = "Egberta", LastName = "hej", Gender = Gender.Female, JudgeNumber = 4, Address = "Gatansgata 18" };
            var judge5 = new Judge { IdNumber = "111111", FirstName = "Egberta", LastName = "hej", Gender = Gender.Female, JudgeNumber = 5, Address = "Gatansgata 19" };

            //Hopp 1
            var dive1_1 = new Dive {Diver = diver1, DiveCode = "5112A", DiveNumber = 1, DiveHeight = 10, QueueOrderNumber = 1};
            var dive1_2 = new Dive { Diver = diver2, DiveCode = "5112A", DiveNumber = 1, DiveHeight = 10, QueueOrderNumber = 2 };
            var dive1_3 = new Dive { Diver = diver3, DiveCode = "5112A", DiveNumber = 1, DiveHeight = 10, QueueOrderNumber = 3 };
            var dive1_4 = new Dive { Diver = diver4, DiveCode = "5112A", DiveNumber = 1, DiveHeight = 10, QueueOrderNumber = 4 };
            var dive1_5 = new Dive { Diver = diver5, DiveCode = "5112A", DiveNumber = 1, DiveHeight = 10, QueueOrderNumber = 5 };
            var dive1_6 = new Dive { Diver = diver6, DiveCode = "5112A", DiveNumber = 1, DiveHeight = 10, QueueOrderNumber = 6 };
            var dive1_7 = new Dive { Diver = diver7, DiveCode = "5112A", DiveNumber = 1, DiveHeight = 10, QueueOrderNumber = 7 };

            //Hopp 2
            var dive2_1 = new Dive{ Diver = diver1, DiveCode = "401B", DiveNumber = 2, DiveHeight = 10, QueueOrderNumber = 8 };
            var dive2_2 = new Dive{ Diver = diver2, DiveCode = "401B", DiveNumber = 2, DiveHeight = 10, QueueOrderNumber = 9 };
            var dive2_3 = new Dive{ Diver = diver3, DiveCode = "401B", DiveNumber = 2, DiveHeight = 10, QueueOrderNumber = 10 };
            var dive2_4 = new Dive{ Diver = diver4, DiveCode = "401B", DiveNumber = 2, DiveHeight = 10, QueueOrderNumber = 11 };
            var dive2_5 = new Dive{ Diver = diver5, DiveCode = "401B", DiveNumber = 2, DiveHeight = 10, QueueOrderNumber = 12 };
            var dive2_6 = new Dive{ Diver = diver6, DiveCode = "401B", DiveNumber = 2, DiveHeight = 10, QueueOrderNumber = 13 };
            var dive2_7 = new Dive{ Diver = diver7, DiveCode = "401B", DiveNumber = 2, DiveHeight = 10, QueueOrderNumber = 14 };

            //Hopp 3
            var dive3_1 = new Dive{ Diver = diver1, DiveCode = "105C", DiveNumber = 3, DiveHeight = 10, QueueOrderNumber = 15 };
            var dive3_2 = new Dive{ Diver = diver2, DiveCode = "105C", DiveNumber = 3, DiveHeight = 10, QueueOrderNumber = 16 };
            var dive3_3 = new Dive{ Diver = diver3, DiveCode = "105C", DiveNumber = 3, DiveHeight = 10, QueueOrderNumber = 17 };
            var dive3_4 = new Dive{ Diver = diver4, DiveCode = "105C", DiveNumber = 3, DiveHeight = 10, QueueOrderNumber = 18 };
            var dive3_5 = new Dive{ Diver = diver5, DiveCode = "105C", DiveNumber = 3, DiveHeight = 10, QueueOrderNumber = 19 };
            var dive3_6 = new Dive{ Diver = diver6, DiveCode = "105C", DiveNumber = 3, DiveHeight = 10, QueueOrderNumber = 20 };
            var dive3_7 = new Dive{ Diver = diver7, DiveCode = "105C", DiveNumber = 3, DiveHeight = 10, QueueOrderNumber = 21 };

            //Hopp 4
            var dive4_1 = new Dive{ Diver = diver1, DiveCode = "6144D", DiveNumber = 4, DiveHeight = 10, QueueOrderNumber = 22 };
            var dive4_2 = new Dive{ Diver = diver2, DiveCode = "6144D", DiveNumber = 4, DiveHeight = 10, QueueOrderNumber = 23 };
            var dive4_3 = new Dive{ Diver = diver3, DiveCode = "6144D", DiveNumber = 4, DiveHeight = 10, QueueOrderNumber = 24 };
            var dive4_4 = new Dive{ Diver = diver4, DiveCode = "6144D", DiveNumber = 4, DiveHeight = 10, QueueOrderNumber = 25 };
            var dive4_5 = new Dive{ Diver = diver5, DiveCode = "6144D", DiveNumber = 4, DiveHeight = 10, QueueOrderNumber = 26 };
            var dive4_6 = new Dive{ Diver = diver6, DiveCode = "6144D", DiveNumber = 4, DiveHeight = 10, QueueOrderNumber = 27 };
            var dive4_7 = new Dive{ Diver = diver7, DiveCode = "6144D", DiveNumber = 4, DiveHeight = 10, QueueOrderNumber = 28 };
            
            //Hopp 5
            var dive5_1 = new Dive{ Diver = diver1, DiveCode = "404B", DiveNumber = 5, DiveHeight = 10, QueueOrderNumber = 29 };
            var dive5_2 = new Dive{ Diver = diver2, DiveCode = "404B", DiveNumber = 5, DiveHeight = 10, QueueOrderNumber = 30 };
            var dive5_3 = new Dive{ Diver = diver3, DiveCode = "404B", DiveNumber = 5, DiveHeight = 10, QueueOrderNumber = 31 };
            var dive5_4 = new Dive{ Diver = diver4, DiveCode = "404B", DiveNumber = 5, DiveHeight = 10, QueueOrderNumber = 32 };
            var dive5_5 = new Dive{ Diver = diver5, DiveCode = "404B", DiveNumber = 5, DiveHeight = 10, QueueOrderNumber = 33 };
            var dive5_6 = new Dive{ Diver = diver6, DiveCode = "404B", DiveNumber = 5, DiveHeight = 10, QueueOrderNumber = 34 };
            var dive5_7 = new Dive{ Diver = diver7, DiveCode = "404B", DiveNumber = 5, DiveHeight = 10, QueueOrderNumber = 35 };
            
            //Lägg alla hopp i hoppkön
            contest.DiveQueue.Add(dive1_1);
            contest.DiveQueue.Add(dive1_2);
            contest.DiveQueue.Add(dive1_3);
            contest.DiveQueue.Add(dive1_4);
            contest.DiveQueue.Add(dive1_5);
            contest.DiveQueue.Add(dive1_6);
            contest.DiveQueue.Add(dive1_7);

            contest.DiveQueue.Add(dive2_1);
            contest.DiveQueue.Add(dive2_2);
            contest.DiveQueue.Add(dive2_3);
            contest.DiveQueue.Add(dive2_4);
            contest.DiveQueue.Add(dive2_5);
            contest.DiveQueue.Add(dive2_6);
            contest.DiveQueue.Add(dive2_7);

            contest.DiveQueue.Add(dive3_1);
            contest.DiveQueue.Add(dive3_2);
            contest.DiveQueue.Add(dive3_3);
            contest.DiveQueue.Add(dive3_4);
            contest.DiveQueue.Add(dive3_5);
            contest.DiveQueue.Add(dive3_6);
            contest.DiveQueue.Add(dive3_7);

            contest.DiveQueue.Add(dive4_1);
            contest.DiveQueue.Add(dive4_2);
            contest.DiveQueue.Add(dive4_3);
            contest.DiveQueue.Add(dive4_4);
            contest.DiveQueue.Add(dive4_5);
            contest.DiveQueue.Add(dive4_6);
            contest.DiveQueue.Add(dive4_7);

            contest.DiveQueue.Add(dive5_1);
            contest.DiveQueue.Add(dive5_2);
            contest.DiveQueue.Add(dive5_3);
            contest.DiveQueue.Add(dive5_4);
            contest.DiveQueue.Add(dive5_5);
            contest.DiveQueue.Add(dive5_6);
            contest.DiveQueue.Add(dive5_7);

            int jumpCount = contest.DiveQueue.Count;

            //Lägg till domare i domarlistan
            contest.JudgeList.Add(judge1);
            contest.JudgeList.Add(judge2);
            contest.JudgeList.Add(judge3);
            contest.JudgeList.Add(judge4);
            contest.JudgeList.Add(judge5);
            contest.JudgeList.GenerateIdStrings();

            contest.Status = ContestStatus.Started;

            int i = 0;
            //Loop som väljer det hopp som är först i kön, och sätter sedan poäng på hoppet.
            while (contest.DiveQueue.Count > 0)
            {
                var firstDive = contest.DiveQueue.First();
                contest.UpdateDiveScore(new DiveScore { Judge = contest.JudgeList[0], Score = 1.0 }, firstDive);
                contest.UpdateDiveScore(new DiveScore { Judge = contest.JudgeList[1], Score = 2.0 }, firstDive);
                contest.UpdateDiveScore(new DiveScore { Judge = contest.JudgeList[2], Score = 3.0 }, firstDive);
                contest.UpdateDiveScore(new DiveScore { Judge = contest.JudgeList[3], Score = 4.0 }, firstDive);
                contest.UpdateDiveScore(new DiveScore { Judge = contest.JudgeList[4], Score = 5.0 }, firstDive);
                contest.UpdateDiveQueue();
                i++;
                Assert.AreEqual(i, contest.DiveHistory.Count);
                Assert.AreEqual(jumpCount - i, contest.DiveQueue.Count);
            }

            Assert.AreEqual(0, contest.DiveQueue.Count);
            Assert.AreEqual(jumpCount, contest.DiveHistory.Count);

            foreach (var dive in contest.DiveHistory)
            {
                //Assert.AreEqual(1.0, dive.JudgeScore[0]);
                //Assert.AreEqual(2.0, dive.JudgeScore[1]);
                //Assert.AreEqual(3.0, dive.JudgeScore[2]);
                //Assert.AreEqual(4.0, dive.JudgeScore[3]);
                //Assert.AreEqual(5.0, dive.JudgeScore[4]);
                //Assert.AreEqual(27, dive.TotalScore);
            }
        }

        [Test]
        public void ContestSimulationWithDb()
        {
            UnitTestMockObjects.ResetDatabase();
            UnitTestMockObjects.ResetObjects();
            DbHandler.Instance.SaveCompleteContestToDb(UnitTestMockObjects._contest1);

            var contest = DbHandler.Instance.LoadContestFromDb(1);
            contest = DbHandler.Instance.ResetContest(contest.DbId);

            contest.Status = ContestStatus.Started;

            int jumpCount = contest.DiveQueue.Count;

            int i = 0;
            //Loop som väljer det hopp som är först i kön, och sätter sedan poäng på hoppet.
            while (contest.DiveQueue.Count > 0)
            {
                var firstDive = contest.DiveQueue.First();
                contest.UpdateDiveScore(new DiveScore { Judge = contest.JudgeList[0], Score = 1.0 }, firstDive);
                contest.UpdateDiveScore(new DiveScore { Judge = contest.JudgeList[1], Score = 2.0 }, firstDive);
                contest.UpdateDiveScore(new DiveScore { Judge = contest.JudgeList[2], Score = 3.0 }, firstDive);
                contest.UpdateDiveQueue();
                i++;
                Assert.AreEqual(i, contest.DiveHistory.Count);
                Assert.AreEqual(jumpCount - i, contest.DiveQueue.Count);
            }

            Assert.AreEqual(0, contest.DiveQueue.Count);
            Assert.AreEqual(jumpCount, contest.DiveHistory.Count);

            foreach (var dive in contest.DiveHistory)
            {
                //Assert.AreEqual(1.0, dive.JudgeScore[0]);
                //Assert.AreEqual(2.0, dive.JudgeScore[1]);
                //Assert.AreEqual(3.0, dive.JudgeScore[2]);
                //Assert.AreEqual(4.0, dive.JudgeScore[3]);
                //Assert.AreEqual(5.0, dive.JudgeScore[4]);
                //Assert.AreEqual(27, dive.TotalScore);
            }
        }
    }
}
